package com.inno.screenrecordhelper;

import android.app.Activity;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author (zijie)
 * @datetime 2021-11-22 13:48
 * @email hezijie@inno-cn.cn
 * @detali：参考：https://cloud.tencent.com/developer/article/1384728
 *  常见的MediaRecorder的几个常见坑：https://blog.csdn.net/csdn_lqr/article/details/54347892
 */
public class VideoRecordManager implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
    private OnVideoRecordListener onVideoRecordListener;
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private MediaRecorder videoRecorder;
    private int curType;
    public static final int VIDEO_RECORD = 1;//视频录制
    public static final int AUDIO_RECORD = 2;//音频录制
    private Camera camera;
    private File mRecordFile;
    private Timer mTimer;  //计时器
    private int mTimeCount;  //时间计数
    private static final String TAG = "111";
    public TextView tvRecordTime;

    public VideoRecordManager(SurfaceView surfaceView, OnVideoRecordListener onVideoRecordListener) {
        this.onVideoRecordListener = onVideoRecordListener;
        this.surfaceView = surfaceView;
        init();
    }

    public VideoRecordManager(TextView tvRecordTime,SurfaceView surfaceView, OnVideoRecordListener onVideoRecordListener) {
        this.onVideoRecordListener = onVideoRecordListener;
        this.surfaceView = surfaceView;
        this.tvRecordTime = tvRecordTime;
        init();
    }

    public VideoRecordManager( OnVideoRecordListener onVideoRecordListener) {
        this.onVideoRecordListener = onVideoRecordListener;

        init();
    }

    public int getCurType() {
        return curType;
    }

    public void setCurType(int curType) {
        this.curType = curType;
    }

    private MyHandler handler = new MyHandler(this);
    /**
     * 录像或录音开始
     * @param type
     */
    public void record(int type) {
        curType = type;
        if (type == VIDEO_RECORD){
            Log.e(TAG, "record: 录像开始" );
        }else {
            Log.e(TAG, "record: 录音开始" );
        }
        createRecordDir(type);
        try {
            if (type == VIDEO_RECORD){
                initCamera();
            }

            initRecord(type);
            mTimeCount = 0;  //时间计数器重新赋值
            mTimer = new Timer();
            mTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    mTimeCount++;
                    Message message = handler.obtainMessage();
                    message.what = mTimeCount;
                    handler.sendMessage(message);

//                    tvRecordTime.setText(mTimeCount + "s");
                }
            }, 0, 1000);  //每隔1000毫秒就重复执行run函数
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "record error: " + e.getMessage());
        }
    }

    private void initRecord(int type) {
        videoRecorder = new MediaRecorder();
        videoRecorder.reset();
        if (camera != null && type == VIDEO_RECORD) {
            videoRecorder.setCamera(camera);
        }
        videoRecorder.setOnErrorListener(this);//设置错误监听器。可监听服务器异常以及未知错误的事件。
        videoRecorder.setOnInfoListener(this);//设置信息监听器。可监听录制结束事件，包括达到录制时长或者达到录制大小。
        if (type == VIDEO_RECORD){
            videoRecorder.setPreviewDisplay(surfaceHolder.getSurface());
            videoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);  //视频源
            videoRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  //音频源,一般使用麦克风
            //设置媒体输出格式OutputFormat.MPEG_4表示MPEG4格式，OutputFormat.THREE_GPP表示3GP格式。该方法要在setVideoEncoder之前调用。
            videoRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            //设置音频编码器。AudioEncoder.AMR_NB表示窄带编码，AudioEncoder.AMR_WB表示宽带编码，AudioEncoder.AAC表示低复杂度的高级编码，AudioEncoder.HE_AAC表示高效率的高级编码，
            videoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  //音频格式
            CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
            Log.e(TAG, "initRecord: " + profile.videoFrameWidth + "---" + profile.videoFrameHeight + profile.videoFrameRate + "---" + profile.videoBitRate );
            videoRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
//            videoRecorder.setVideoSize(640, 480);  //设置分辨率：,如果设备不支持，会报错
            videoRecorder.setVideoFrameRate(profile.videoFrameRate);  //setVideoFrameRate与setVideoEncodingBitRate设置其一即可,如果设备不支持，会报错,使用默认值
            videoRecorder.setVideoEncodingBitRate(profile.videoBitRate);  //设置帧频率，然后就清晰了
            videoRecorder.setOrientationHint(180);  //输出旋转90度，保持竖屏录制
            videoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);  //视频录制格式
//        videoRecorder.setMaxDuration(mRecordMaxTime * 1000);  //设置录制时长
//            videoRecorder.setMaxFileSize(1024*1024*10);  //setMaxFileSize与setMaxDuration设置其一即可
        }else if (type == AUDIO_RECORD){
            videoRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  //音频源,一般使用麦克风
            //设置媒体输出格式。OutputFormat.AMR_NB表示窄带格式，OutputFormat.AMR_WB表示宽带格式，AAC_ADTS表示高级的音频传输流格式。
            // 该方法要在setVideoEncoder之前调用，不然调用setAudioEncoder时会报错“java.lang.IllegalStateException”。
            videoRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            //设置音频编码器。AudioEncoder.AMR_NB表示窄带编码，AudioEncoder.AMR_WB表示宽带编码，AudioEncoder.AAC表示低复杂度的高级编码，AudioEncoder.HE_AAC表示高效率的高级编码，
            videoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);  //音频格式
//            videoRecorder.setAudioSamplingRate();//设置音频的采样率，单位赫兹（Hz）。该方法为可选，AMRNB默认8khz，AMRWB默认16khz。
            videoRecorder.setAudioChannels(2);// : 设置音频的声道数。1表示单声道，2表示双声道。该方法为可选
            videoRecorder.setAudioEncodingBitRate(2 * 1024 * 512);// : 设置音频每秒录制的字节数。越大则音频越清晰。该方法为可选

        }

        videoRecorder.setOutputFile(mRecordFile.getAbsolutePath());
        try {
            videoRecorder.prepare();
            videoRecorder.start();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "MediaRecorder.start error: " + e.getMessage());
        }
    }

    public void initCamera() throws IOException {
        if (camera != null) {
            freeCameraResource();
        }
        try {
            camera = Camera.open(1);
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("111", "Camera.open() error: " + e.getMessage());
            freeCameraResource();
        }
        if (camera == null) {
            return;
        }
        setCameraParams();
//        camera.setDisplayOrientation(90);
        camera.setPreviewDisplay(surfaceHolder);
        camera.startPreview();
        camera.unlock();
    }

    //设置摄像头为竖屏
    private void setCameraParams() {
        if (camera != null) {
            Camera.Parameters params = camera.getParameters();
            params.set("orientation", "portrait");
            camera.setParameters(params);
        }
    }

    private void createRecordDir(int type) {
        File sampleDir = new File(Environment.getExternalStorageDirectory()
                + File.separator + "RecordVideo/");
        if (!sampleDir.exists()) {
            sampleDir.mkdirs();
        }
        File recordDir = sampleDir;
        try {
            if (type == VIDEO_RECORD){
                mRecordFile = File.createTempFile("recording", ".mp4", recordDir);
            }else if (type == AUDIO_RECORD){
                mRecordFile = File.createTempFile("recording", ".mp3", recordDir);
            }

            Log.d(TAG, mRecordFile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "createTempFile error: " + e.getMessage());
        }
    }



    private void init() {
        surfaceHolder = surfaceView.getHolder();
        videoRecorder = new MediaRecorder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
//                try {
//                    initCamera();
//                } catch (IOException e) {
//                    Log.d(TAG, "surfaceCreated error: " + e.getMessage());
//                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                if (curType == VIDEO_RECORD){
                    freeCameraResource();
                }
            }
        });
    }

    private void freeCameraResource() {
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.stopPreview();
            camera.lock();
            camera.release();
            camera = null;
        }
    }

    @Override
    public void onError(MediaRecorder mr, int what, int extra) {
        Log.e(TAG, "onError: " + extra );
        if (mr != null) {
            mr.reset();
        }
    }

    @Override
    public void onInfo(MediaRecorder mr, int what, int extra) {
        Log.e(TAG, "onInfo: " + extra );
        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED
                || what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED ) {

            //录制完成，
            Log.e(TAG, "onInfo: 录制完成");
        }
    }

    /**
     * 停止录像或者录音
     * @param type
     */
    public void stop(int type) {
        if (type == VIDEO_RECORD){
            Log.e(TAG, "record: 录像结束" );
        }else  {
            Log.e(TAG, "record: 录音结束" );
        }
        curType = -1;
        stopRecord(type);
        releaseRecord();
        if (type == VIDEO_RECORD){
            freeCameraResource();
        }

    }

    private void stopRecord(int type) {
        if (type == VideoRecordManager.VIDEO_RECORD || type == VideoRecordManager.AUDIO_RECORD){
            if (mTimer != null) {
                mTimer.cancel();
            }
            if (videoRecorder != null) {
                videoRecorder.setOnErrorListener(null);
                videoRecorder.setPreviewDisplay(null);
                try {
                    videoRecorder.stop();
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d(TAG, "MediaRecorder.stop error: " + e.getMessage());
                }
            }
        }
    }

    private void releaseRecord() {
        if (videoRecorder != null) {
            videoRecorder.setOnErrorListener(null);
            videoRecorder.release();
            videoRecorder = null;
        }
    }

    public void onDestroy() {
        stop(curType);
        handler.removeCallbacksAndMessages(null);
    }

    static class MyHandler extends Handler{

        private WeakReference<VideoRecordManager> weakReference;

        public MyHandler(VideoRecordManager videoRecordManager) {
            this.weakReference = new WeakReference<>(videoRecordManager);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            VideoRecordManager videoRecordManager = weakReference.get();
            videoRecordManager.tvRecordTime.setText(msg.what + "s");
        }
    }

    public interface OnVideoRecordListener {
        /**
         * 录制开始时隐藏不必要的UI
         */
        void onBeforeRecord();

        /**
         * 开始录制
         */
        void onStartRecord();

        /**
         * 取消录制
         */
        void onCancelRecord();

        /**
         * 结束录制
         */
        void onEndRecord();
    }
}
